#ifndef VECTORSL_HPP
#define VECTORSL_HPP
//=========================================================
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include <assert.h>
#include <math.h>
//=========================================================
//  CLASS VECTOR
//=========================================================
class vector{
  size_t dim;
  double *vec;
public:
  vector(){
    this->dim = 0;
    this->vec = NULL;
  };
  //-------------------------------------------------------
  vector(size_t size){
    this->vec = (size)?new double[size] : NULL;
    if(size != 0){
      this->dim = size;
      for(size_t i=0; i<size; i++){
        this->vec[i] = 0;
      }
    }else{ dim = 0; }
  };
  //-------------------------------------------------------
  vector(size_t size, double *g){
    this->vec = (size)?new double[size] : NULL;
    if(size != 0){
      this->dim = size;
      for(size_t i=0; i<size; i++){
        this->vec[i] = g[i];
      }
    }else{ dim = 0; }
  };
  //-------------------------------------------------------
  ~vector(){
    delete [] this->vec;
  };
  //-------------------------------------------------------
  vector(const vector &a){
    this->dim = a.dim;
    if(this->dim){
      this->vec = new double[this->dim];
      for(size_t i=0; i<this->dim; ++i)
        this->vec[i] = a.vec[i];
    }else{ this->vec = NULL; }
  };
  //-------------------------------------------------------
  size_t retdim() const{
    return this->dim;
  };
  //-------------------------------------------------------
  //-------------------------------------------------------
  double& operator [](size_t a){
    return this->vec[a];
  };
  //-------------------------------------------------------
  const double operator [](size_t a) const{
    return this->vec[a];
  };
  //-------------------------------------------------------
  //-------------------------------------------------------
  //vector = vector
  vector& operator=(const vector &b){
    if(this != &b){
      delete [] this->vec;
      this->dim = b.dim;
      if(this->dim){
        this->vec = new double[this->dim];
        for(size_t i=0; i<this->dim; ++i)
          this->vec[i] = b.vec[i];
      }else{ this->vec = NULL; }
    }
    return *this;
  };
  //-------------------------------------------------------
  //vector + vector
  vector operator+(vector &b){
    vector sum;
    assert(this->dim == b.dim);
    if(this->dim == b.dim){
      sum.dim = this->dim;
      sum.vec = new double[this->dim];
      for(size_t i=0; i<this->dim; i++){
        sum.vec[i] = this->vec[i]+b.vec[i];
      }
    }
    return sum;
  };
  //-------------------------------------------------------
  //vector - vector
  vector operator-(vector &b){
    vector raz;
    assert(this->dim == b.dim);
    if(this->dim == b.dim){
      raz.dim = this->dim;
      raz.vec = new double[this->dim];
      for(size_t i=0; i<this->dim; i++){
        raz.vec[i] = this->vec[i]-b.vec[i];
      }
    }
    return raz;
  };
  //-------------------------------------------------------
  //vector == vector
  bool operator==(vector &b){
    assert(this->dim == b.dim);
    for(size_t i=0; i<this->dim; i++){
      if(this->vec[i] != b.vec[i])
        return 0;
    }
    return 1;
  };
  //-------------------------------------------------------
  friend vector operator*(double a, vector &b);
  friend vector operator*(vector &b, double a);
  friend vector operator/(vector &b, double a);
  friend vector operator*(vector &a, vector &b);
};
//---------------------------------------------------------
//---------------------------------------------------------
//vector norm
double norma(vector &p){
  double norm = 0;
  for(size_t i=0; i<p.retdim(); i++){
    norm = norm+(p[i]*p[i]);
  }
  return sqrt(norm);
};
//---------------------------------------------------------
//print vector
void print(const vector &p,FILE *fi){
  size_t size = p.retdim();
  if(size != 0){ 
    fprintf(fi,"( ");
    for(size_t i=0; i<size; i++){
      fprintf(fi,"%g", p[i]);
      if(i != size-1) fprintf(fi,", ");
    }
    fprintf(fi,") \n");
  }
};
//---------------------------------------------------------
//vector * a
vector operator*(double a, vector &b){
  vector sca;
  sca.dim = b.dim;
  sca.vec = new double[b.dim];
  for(size_t i=0; i<b.dim; i++){
    sca.vec[i] = a*b.vec[i];
    if(sca.vec[i] == 0) sca.vec[i] = abs(sca.vec[i]);
  }
  return sca;
};
//---------------------------------------------------------
//a * vector
vector operator*(vector &b, double a){
  vector sca;
  sca.dim = b.dim;
  sca.vec = new double[b.dim];
  for(size_t i=0; i<b.dim; i++){
    sca.vec[i] = a*b.vec[i];
    if(sca.vec[i] == 0) sca.vec[i] = abs(sca.vec[i]);
  }
  return sca;
};
//---------------------------------------------------------
//vector / a
vector operator/(vector &b, double a){
  assert(a != 0);
  double p = 1/a;
  return b*p;
};
//---------------------------------------------------------
//(vector,vector)
vector operator*(vector &a, vector &b){
  assert(a.dim == b.dim);
  if(a.dim == b.dim){
    vector sca(a.dim);
    sca.dim = a.dim;
    for(size_t i=0; i<a.dim; i++){
      sca[i] = a[i]*b[i];
      if(sca[i] == 0) sca[i] = abs(sca[i]);
    }
    return sca;
  }
  exit(1);
};
//=========================================================
#endif